home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 May: Tool Chest / Developer CD Series Tool Chest (Apple Computer)(May 1999).iso / Tool Chest / Toolbox / Menu Defproc 1.0.3 / DrawTkl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-29  |  17.1 KB  |  468 lines  |  [TEXT/MPS ]

  1. /*============================================================================*\
  2. * DrawTkl.c - mDrawMsg handler
  3. *
  4. * DrawTkl.c contains the code to process the mDrawMsg message from the Menu
  5. * Manager.  This source file contains the routines to do ALL drawing, including
  6. * the scroll icons.
  7. \*============================================================================*/
  8.  
  9.  
  10. /******************************************************************************\
  11. * Header Files
  12. \******************************************************************************/
  13.  
  14. #include <Memory.h>
  15. #include <Menus.h>
  16. #include <Resources.h>
  17. #include <ToolUtils.h>
  18. #include <Types.h>
  19. #include "Concordia.h"
  20. #include "DrawTkl.h"
  21. #include "SizeTkl.h"
  22.  
  23.  
  24. /******************************************************************************\
  25. * Constants & Macros
  26. \******************************************************************************/
  27.  
  28. #define scrlSICNID -12288 //Resource ID of scroll arrows SICN
  29.  
  30.  
  31. /******************************************************************************\
  32. * Type Declarations
  33. \******************************************************************************/
  34.  
  35. /* Small icon data */
  36. typedef Byte SICNData [32];
  37.  
  38.  
  39. /******************************************************************************\
  40. * Function Prototypes
  41. \******************************************************************************/
  42.  
  43. void DimRect (Rect *);
  44. void DrawSICN (SICNData **, short, short, short);
  45. void DrawICON (Handle, Rect *);
  46.  
  47.  
  48. #pragma segment Main
  49. /******************************************************************************\
  50. * DoDrawMsg - Draw a menu
  51. *
  52. * DoDrawMsg draws the menu specified by TheMenu.  The rectangle in global coord-
  53. * inates that the menu occupies is specified in MenuRect.  If the system global
  54. * TopMenuItem is not equal to the top coordinate of MenuRect, a top scroll bar
  55. * is drawn.  If the menu extends below the bottom of MenuRect, a bottom scroll
  56. * bar is drawn.  The Menu Manager (I guess) sets TopMenuItem properly for pull-
  57. * down menus, while the popup menu tackler (DoPopupMsg) sets TopMenuItem
  58. * properly for popup menus.  DoDrawMsg sets the system global AtMenuBottom to
  59. * the bottom of the entire menu, regardless of whether it fits on the screen or
  60. * not.
  61. *
  62. * Coding Notes
  63. * #A# - The sole purpose of this loop is to find the total height of the menu in 
  64. *       pixels ignoring the size of the screen.  Seems like kind of a waste,
  65. *       doesn't it?
  66. * #B# - The clip rectangle, MenuClip is only set if the menu has scroll icons.
  67. *       This is determined here.
  68. * #C# - This loop draws each of the menu items.
  69. * #D# - Side-effect: system global AtMenuBottom set to coordinate of bottom of
  70. *       Menu regardless of whether the menu fits or not.
  71. * #E# - We don’t need the menuEnabled bit any more so get rid of it by shifting
  72. *       it out.  Then we have to set the high bit so that all items beyond the
  73. *       31st will be enabled.  With arithmetic right shifting, this high bit
  74. *       will be preserved.
  75. \******************************************************************************/
  76.  
  77. void
  78. DoDrawMsg (TheMenu, MenuRect)
  79.     MenuHandle TheMenu;   //=> Menu to draw >>
  80.     Rect       *MenuRect; //-> Menu's rectangle in global coords >>
  81.     {
  82.     Str255      *ItemString; //-> Menu item's string
  83.     ItemInfoPtr ItemInfo;    //-> Item info
  84.     Rect        ItemRect;    //Item's rectangle
  85.     Rect        TotMenuRect; //Menu's rectangle w/o clipping to screen
  86.     RgnHandle   SaveClip;    //=> Saved clip region
  87.     Rect        MenuClip;    //Clip region of menu if menu scrolls
  88.     long        EnableFlags; //Menu's enable flags
  89.  
  90.     SaveClip = (RgnHandle) null;
  91.     if ((**TheMenu).enableFlags & 1)
  92.         {
  93.         EnableFlags = (unsigned long) (**TheMenu).enableFlags >> 1; //#E#
  94.         EnableFlags |= 0x80000000;
  95.         }
  96.     else
  97.         EnableFlags = 0;
  98.     SetRect (&TotMenuRect, MenuRect->left, sgTopMenuItem, MenuRect->right,
  99.             sgTopMenuItem);
  100.     HLock ((Handle) TheMenu);
  101.     ItemString = (Str255 *) (**TheMenu).menuData;
  102.     ItemString = (Str255 *) ((Byte *) ItemString + strSize (*ItemString));
  103.     while ((*ItemString) [0] != (char) 0) //#A#
  104.         {
  105.         ItemInfo = (ItemInfoPtr) ((Byte *) *ItemString + strSize (*ItemString));
  106.         TotMenuRect.bottom += CalcItemHeight (*ItemString, ItemInfo);
  107.         ItemString = (Str255 *) (ItemInfo + 1);
  108.         }
  109.     HUnlock ((Handle) TheMenu);
  110.     MenuClip = *MenuRect;
  111.     if (TotMenuRect.top != MenuRect->top || TotMenuRect.bottom != MenuRect->
  112.             bottom) //#B#
  113.         {
  114.         if (TotMenuRect.top != MenuRect->top)
  115.             {
  116.             DrawScroll (MenuRect, topScroll);
  117.             MenuClip.top += scrlIconHeight;
  118.             }
  119.         if (TotMenuRect.bottom != MenuRect->bottom)
  120.             {
  121.             DrawScroll (MenuRect, botScroll);
  122.             MenuClip.bottom -= scrlIconHeight;
  123.             }
  124.         SaveClip = NewRgn ();
  125.         GetClip (SaveClip);
  126.         ClipRect (&MenuClip);
  127.         }
  128.     HLock ((Handle) TheMenu);
  129.     ItemString = (Str255 *) (**TheMenu).menuData;
  130.     ItemString = (Str255 *) ((Byte *) ItemString + strSize (*ItemString));
  131.     ItemRect = TotMenuRect;
  132.     ItemRect.bottom = ItemRect.top;
  133.     while ((*ItemString) [0] != (char) 0) //#C#
  134.         {
  135.         ItemInfo = (ItemInfoPtr) ((Byte *) *ItemString + strSize (*ItemString));
  136.         ItemRect.bottom += CalcItemHeight (*ItemString, ItemInfo);
  137.         if (ItemRect.bottom > MenuClip.top && ItemRect.top < MenuClip.bottom)
  138.             DrawItem (*ItemString, ItemInfo, &ItemRect, (short) (EnableFlags &
  139.                     1));
  140.         ItemString = (Str255 *) (ItemInfo + 1);
  141.         ItemRect.top = ItemRect.bottom;
  142.         EnableFlags >>= 1;
  143.         }
  144.     HUnlock ((Handle) TheMenu);
  145.     if (SaveClip != (RgnHandle) null)
  146.         {
  147.         SetClip (SaveClip);
  148.         DisposeRgn (SaveClip);
  149.         }
  150.     sgAtMenuBottom = TotMenuRect.bottom; //#D#
  151.     *((short *) ((*sgMBSaveLoc) + 16)) = 1;
  152.     }
  153.  
  154.  
  155. #pragma segment Main
  156. /******************************************************************************\
  157. * DrawItem - Draw a menu item
  158. *
  159. * DrawItem draws a menu item whose text is specified by ItemString and whose
  160. * item information is specified by ItemData.  The rectangle that the item
  161. * occupies on the screen is specified by ItemRect.  If the item is enabled,
  162. * Enabled must be true, otherwise it must be false.  DrawItem also draws mark
  163. * characters (like check marks); big, scaled, and disabled icons, dims items if
  164. * they're not enabled, and draws gray lines if the item string begins with a
  165. * hyphen.  Any command key characters that aren't printable are ignored.  If the
  166. * specified item icon can't be found, it is not drawn (of course), but space is
  167. * left for it.
  168. *
  169. * Coding Notes:
  170. * #A# - This calculation figures out the proper vertical coordinate to begin
  171. *       drawing the item string so that it's centered vertically in ItemRect.
  172. * #B# - Draw the mark character unless this is a hierarchical menu item.
  173. * #C# - Draw the command-key equivalent
  174. * #E# - Draw the item icon
  175. * #F# - With these command-key equivalents, icons are half their size.
  176. * #G# - If couldn't load icon, ignore drawing and continue
  177. * #H# - With this command-key equivalent, icon is dimmed.
  178. * #I# - These values will be used to set the location of the item string.
  179. \******************************************************************************/
  180.  
  181. void
  182. DrawItem (ItemString, ItemData, ItemRect, Enabled)
  183.     Str255      ItemString; //Name of menu item >>
  184.     ItemInfoPtr ItemData;   //Information for menu item >>
  185.     Rect        *ItemRect;  //-> Item's rectangle in screen coords >>
  186.     short       Enabled;    //True if item enabled >>
  187.     {
  188.     short        HorzPos;   //Horizontal position to draw item
  189.     short        VertPos;   //Vertical position to draw item
  190.     short        MarkWidth; //Width of item mark
  191.     Handle       ItemIcon;  //=> Item's icon
  192.     Rect         IconRect;  //Rectangle of icon
  193.     short        IconSize;  //Size of icon in pixels
  194.     FontInfo     CurrFont;  //Current font's characteristics
  195.     PenState     CurrPen;   //Current characteristics of graphics pen
  196.     short        CurrFile;  //Refnum of current resource file
  197.     SICNData     **SICNRes; //=> SICN resource
  198.     TextStateRec TextState; //Current characteristics of text drawing
  199.  
  200.     GetPenState (&CurrPen);
  201.     if (ItemString [1] == '-')
  202.         {
  203.         PenSize (1, 1);
  204.         PenMode (patOr);
  205.         PenPat (qdGlobPtr->gray);
  206.         MoveTo (ItemRect->left, ItemRect->top + ItemRect->bottom >> 1);
  207.         Line (ItemRect->right - ItemRect->left, 0);
  208.         }
  209.     else
  210.         {
  211.         PenMode (patOr);
  212.         GetTextState (&TextState);
  213.         TextFace (normal);
  214.         TextMode (srcOr);
  215.         GetFontInfo (&CurrFont);
  216.         MarkWidth = CurrFont.widMax;
  217.         if (ItemData->markChar != '\0' || ItemData->kbdEquiv != '\0')
  218.             {
  219.             VertPos = ((short) ((ItemRect->bottom - ItemRect->top) - (CurrFont.
  220.                     ascent + CurrFont.descent + CurrFont.leading) >> 1) +
  221.                     CurrFont.ascent + ItemRect->top); //#A#
  222.             if (ItemData->markChar != (char) 0 && ItemData->kbdEquiv !=
  223.                     hMenuCmd) //#B#
  224.                 {
  225.                 HorzPos = ItemRect->left + itemHorzMarg;
  226.                 MoveTo (HorzPos, VertPos);
  227.                 DrawChar (ItemData->markChar);
  228.                 }
  229.             if (ItemData->kbdEquiv > '!') //#C#
  230.                 {
  231.                 HorzPos = ItemRect->right - itemHorzMarg -
  232.                         CurrFont.widMax - CharWidth (cmmdCharCode);
  233.                 MoveTo (HorzPos, VertPos);
  234.                 DrawChar (cmmdCharCode);
  235.                 DrawChar (ItemData->kbdEquiv);
  236.                 }
  237.             else if (ItemData->kbdEquiv == hMenuCmd)
  238.                 {
  239.                 HorzPos = ItemRect->right - sicnSize;
  240.                 VertPos = (short) ((ItemRect->bottom - ItemRect->top - (short)
  241.                         sicnSize) >> 1) + ItemRect->top;
  242.                 CurrFile = CurResFile ();
  243.                 UseResFile (0);
  244.                 if ((SICNRes = (SICNData **) Get1Resource ('SICN', scrlSICNID))
  245.                         != (SICNData **) null)
  246.                     DrawSICN (SICNRes, heirArrow, HorzPos, VertPos);
  247.                 UseResFile (CurrFile);
  248.                 }
  249.             }
  250.         if (ItemData->iconNum != (Byte) 0) //#E#
  251.             {
  252.             IconSize = iconSize;
  253.             if (ItemData->kbdEquiv == (char) 0x1D || ItemData->kbdEquiv ==
  254.                     (char) 0x1F) //#F#
  255.                 IconSize >>= 1;
  256.             if ((ItemIcon = GetIcon (ItemData->iconNum + 256)) != (Handle) null) //#G#
  257.                 {
  258.                 IconRect.top = (ItemRect->bottom - ItemRect->top -
  259.                         IconSize >> 1) + ItemRect->top;
  260.                 IconRect.left = ItemRect->left + itemHorzMarg + MarkWidth +
  261.                         markItemGap;
  262.                 IconRect.bottom = IconRect.top + IconSize;
  263.                 IconRect.right = IconRect.left + IconSize;
  264.                 DrawICON (ItemIcon, &IconRect);
  265.                 if (ItemData->kbdEquiv == (char) 0x1F) //#H#
  266.                     DimRect (&IconRect);
  267.                 }
  268.             IconSize += iconItemGap; //#I#
  269.             }
  270.         else
  271.             IconSize = 0; //#I#
  272.         TextFace (ItemData->charStyle);
  273.         GetFontInfo (&CurrFont);
  274.         VertPos = (short) ((ItemRect->bottom - ItemRect->top) - (CurrFont.
  275.                 ascent + CurrFont.descent + CurrFont.leading) >> 1) + CurrFont.
  276.                 ascent + ItemRect->top;
  277.         HorzPos = ItemRect->left + itemHorzMarg + MarkWidth + markItemGap +
  278.                 IconSize;
  279.         MoveTo (HorzPos, VertPos);
  280.         DrawString (ItemString);
  281.         SetTextState (&TextState);
  282.         if (! Enabled)
  283.             DimRect (ItemRect);
  284.         }
  285.     SetPenState (&CurrPen);
  286.     }
  287.  
  288.  
  289. #pragma segment Main
  290. /******************************************************************************\
  291. * DimRect - Dim a rectangle
  292. *
  293. * DimRect dims the rectangle specified by ItemRect by bit-clearing it with a
  294. * medium gray pattern.  Normally, we could do this just by drawing over the item
  295. * with the standard gray pattern, but there's a problem: what if the menu has
  296. * scrolled an odd number of pixels and we have to draw part of a dimmed menu
  297. * item?  We'll end up with the gray pattern that's out of phase with the part of
  298. * the menu item that was already drawn.  To solve this, DimRect creates its own
  299. * pattern "on the fly" in GrayPat.  Two gray patterns can be created, each one
  300. * being out of out of phase with the other by one pixel.  The particular pattern
  301. * is chosen by checking to see whether the system global, TopMenuItem, is odd or
  302. * even.  The current pen state is unchanged.
  303. \******************************************************************************/
  304.  
  305. static void
  306. DimRect (TheRect)
  307.     Rect *TheRect; //-> Rectangle to dim >>
  308.     {
  309.     PenState CurrPen;     //Current characteristics of graphics pen
  310.     short    PatElem;     //Pattern element
  311.     short    GrayPat [4]; //Gray pattern (not 8 bytes 'cause it's easier here
  312.     short    PatInd;      //Index into pattern array
  313.  
  314.     GetPenState (&CurrPen);
  315.     PenMode (patBic);
  316.     if ((sgTopMenuItem & 0x0001) == 0)
  317.         PatElem = (short) 0xAA55;
  318.     else
  319.         PatElem = (short) 0x55AA;
  320.     for (PatInd = 0; PatInd < 4; PatInd++)
  321.         GrayPat [PatInd] = PatElem;
  322.     PenPat ((Pattern) GrayPat);
  323.     PaintRect (TheRect);
  324.     SetPenState (&CurrPen);
  325.     }
  326.  
  327.  
  328. #pragma segment Main
  329. /******************************************************************************\
  330. * DrawScroll - Draw a scroll arrow
  331. *
  332. * DrawScroll draws a top scroll arrow if Which is topScroll, and it draws a
  333. * bottom scroll arrow if which is botScroll.  The menu's rectangle must be
  334. * specified in MenuRect.
  335. \******************************************************************************/
  336.  
  337. void
  338. DrawScroll (MenuRect, Which)
  339.     Rect  *MenuRect; //-> Menu's rectangle >>
  340.     short Which;     //topScroll=draw top arrow, botScroll=draw bottom arrow >>
  341.     {
  342.     SICNData **SICNRes; //=> SICN resource
  343.     short    HorzPos;   //Horizontal position of icon
  344.     short    VertPos;   //Vertical position of icon
  345.     Rect     ScrlRect;  //Rectangle of scroll icon area
  346.     PenState CurrPen;   //Current pen state
  347.     short    CurrFile;  //Current resource file's refnum
  348.  
  349.     HorzPos = (short) ((MenuRect->right - MenuRect->left - sicnSize) >> 1) +
  350.             MenuRect->left;
  351.     ScrlRect = *MenuRect;
  352.     GetPenState (&CurrPen);
  353.     PenPat (qdGlobPtr->black);
  354.     PenMode (patCopy);
  355.     PenSize (1, 1);
  356.     if (Which == topScroll)
  357.         {
  358.         ScrlRect.bottom = ScrlRect.top + scrlIconHeight;
  359.         EraseRect (&ScrlRect);
  360.         MoveTo (MenuRect->left, MenuRect->top + scrlIconHeight - 1);
  361.         Line (MenuRect->right - MenuRect->left, 0);
  362.         VertPos = MenuRect->top + 1;
  363.         }
  364.     else
  365.         {
  366.         ScrlRect.top = ScrlRect.bottom - scrlIconHeight;
  367.         EraseRect (&ScrlRect);
  368.         MoveTo (MenuRect->left, MenuRect->bottom - scrlIconHeight);
  369.         Line (MenuRect->right - MenuRect->left, 0);
  370.         VertPos = MenuRect->bottom - 1 - sicnSize;
  371.         }
  372.     PenMode (patOr);
  373.     CurrFile = CurResFile ();
  374.     UseResFile (0);
  375.     if ((SICNRes = (SICNData **) Get1Resource ('SICN', scrlSICNID)) !=
  376.             (SICNData **) null)
  377.         DrawSICN (SICNRes, Which, HorzPos, VertPos);
  378.     UseResFile (CurrFile);
  379.     SetPenState (&CurrPen);
  380.     }
  381.  
  382.  
  383. #pragma segment Main
  384. /******************************************************************************\
  385. * DrawSICN - Draw a small icon
  386. *
  387. * DrawSICN draws the small icon specified by TheIcon into the current port.
  388. * Each SICNData can hold any number of SICNs, so Index specifies which SICN to
  389. * draw, 0 specifying the first.  HorzPos and VertPos specify the horizontal and
  390. * vertical position to draw the top-left corner of the icon in local
  391. * coordinates.  If TheIcon doesn't specify a SICN or if Index is out of range,
  392. * garbage will be drawn.  The transfer mode will be the equivalent of the
  393. * current pen mode of the current port.  For example, if the current pen mode is
  394. * patXor, the SICN will be drawn in srcXor mode.
  395. \******************************************************************************/
  396.  
  397. static void
  398. DrawSICN (TheIcon, Index, HorzPos, VertPos)
  399.     SICNData **TheIcon; //=> Icon data >>
  400.     short    Index;     //Index of icon to draw >>
  401.     short    HorzPos;   //Horizontal position of left edge of icon >>
  402.     short    VertPos;   //Vertical position of top edge of icon >>
  403.     {
  404.     BitMap  IconBits;  //Bitmap for icon
  405.     GrafPtr CurrPort;  //-> Current GrafPort
  406.     Rect    SICNRect;  //Rectangle to draw icon into
  407.     short   TransMode; //Transfer mode to use
  408.  
  409.     HLock ((Handle) TheIcon);
  410.     SetRect (&IconBits.bounds, 0, 0, sicnSize, sicnSize);
  411.     IconBits.rowBytes = 2;
  412.     IconBits.baseAddr = (Ptr) (*TheIcon + Index);
  413.     SetRect (&SICNRect, HorzPos, VertPos, HorzPos + sicnSize, VertPos +
  414.             sicnSize);
  415.     GetPort (&CurrPort);
  416.     if (CurrPort->pnMode == patCopy || CurrPort->pnMode == notPatCopy)
  417.         TransMode = srcCopy;
  418.     else if (CurrPort->pnMode == patOr || CurrPort->pnMode == notPatOr)
  419.         TransMode = srcOr;
  420.     else if (CurrPort->pnMode == patXor || CurrPort->pnMode == notPatXor)
  421.         TransMode = srcXor;
  422.     else if (CurrPort->pnMode == patBic || CurrPort->pnMode == notPatBic)
  423.         TransMode = srcBic;
  424.     CopyBits (&IconBits, &CurrPort->portBits, &IconBits.bounds, &SICNRect,
  425.             TransMode, (RgnHandle) null);
  426.     HUnlock ((Handle) TheIcon);
  427.     }
  428.  
  429.  
  430. #pragma segment Main
  431. /******************************************************************************\
  432. * DrawICON - Draw an icon
  433. *
  434. * DrawICON draws the icon specified by TheIcon into the current port.  IconRect
  435. * specifies the size and location to draw the icon in local coordinates.  If
  436. * TheIcon doesn't specify an ICON, garbage will be drawn.  The transfer mode
  437. * will be the equivalent of the current pen mode of the current port.  For
  438. * example, if the current pen mode is patXor, the ICON will be drawn in srcXor
  439. * mode.
  440. \******************************************************************************/
  441.  
  442. static void
  443. DrawICON (TheIcon, IconRect)
  444.     Handle TheIcon; //=> Icon data >>
  445.     Rect   *IconRect; //-> Rectangle to draw icon into >>
  446.     {
  447.     BitMap  IconBits;  //Bitmap for icon
  448.     GrafPtr CurrPort;  //-> Current GrafPort
  449.     short   TransMode; //Transfer mode to use
  450.  
  451.     HLock (TheIcon);
  452.     SetRect (&IconBits.bounds, 0, 0, iconSize, iconSize);
  453.     IconBits.rowBytes = 4;
  454.     IconBits.baseAddr = *TheIcon;
  455.     GetPort (&CurrPort);
  456.     if (CurrPort->pnMode == patCopy || CurrPort->pnMode == notPatCopy)
  457.         TransMode = srcCopy;
  458.     else if (CurrPort->pnMode == patOr || CurrPort->pnMode == notPatOr)
  459.         TransMode = srcOr;
  460.     else if (CurrPort->pnMode == patXor || CurrPort->pnMode == notPatXor)
  461.         TransMode = srcXor;
  462.     else if (CurrPort->pnMode == patBic || CurrPort->pnMode == notPatBic)
  463.         TransMode = srcBic;
  464.     CopyBits (&IconBits, &CurrPort->portBits, &IconBits.bounds, IconRect,
  465.             TransMode, (RgnHandle) null);
  466.     HUnlock (TheIcon);
  467.     }
  468.